
/*
 * Copyright (C) Igor Sysoev
 * Copyright (C) Nginx, Inc.
 */


#ifndef _NGX_HTTP_UPSTREAM_ROUND_ROBIN_H_INCLUDED_
#define _NGX_HTTP_UPSTREAM_ROUND_ROBIN_H_INCLUDED_


#include <ngx_config.h>
#include <ngx_core.h>
#include <ngx_http.h>


typedef struct {
    struct sockaddr                *sockaddr;
    socklen_t                       socklen;
    ngx_str_t                       name;

    ngx_int_t                       current_weight;
    ngx_int_t                       effective_weight;
    ngx_int_t                       weight;

    ngx_uint_t                      fails; //fzc: 当前已经访问失败的次数
    time_t                          accessed;
    time_t                          checked; //fzc: 记录开启屏蔽超时的起始时间

    ngx_uint_t                      max_fails;
    time_t                          fail_timeout;

    ngx_uint_t                      down;          /* unsigned  down:1; */

#if (NGX_HTTP_SSL)
    ngx_ssl_session_t              *ssl_session;   /* local to a process */
#endif
} ngx_http_upstream_rr_peer_t; //fzc: 一个server根据ip地址对应多个peer, 静态peer数据, 与动态peer数据不同的是, 静态peer数据全局的, 在ngx_http_upstream_init_main_conf->init_upstream即ngx_http_upstream_init_round_robin中创建


typedef struct ngx_http_upstream_rr_peers_s  ngx_http_upstream_rr_peers_t;

struct ngx_http_upstream_rr_peers_s { //fzc: 用作组织动态数组, 最后一个是动态数组指针, 组织静态peer数组
    ngx_uint_t                      number; //fzc: upstream中peer的个数, 而非一个server的peer个数

 /* ngx_mutex_t                    *mutex; */

    ngx_uint_t                      total_weight; //fzc: 所有peer的weight总和

    unsigned                        single:1; //fzc: upstream中是否只有一个peer
    unsigned                        weighted:1; //fzc: 是否使用加权算法, 当计算得到的n == w则认为不使用. 

    ngx_str_t                      *name; //fzc: upstream的name, 即ngx_http_upstream_srv_conf_t->host

    ngx_http_upstream_rr_peers_t   *next; //fzc: nginx rr算法全局会建造两个peer数组, 非backup数组指向backup数组

    ngx_http_upstream_rr_peer_t     peer[1];
};


typedef struct {
    ngx_http_upstream_rr_peers_t   *peers; //fzc: 指向在init_upstream建立的ngx_http_upstream_srv_conf_t->peer.data, 其实就是上面的ngx_http_upstream_rr_peers_s, 即构成动态peer数据包含了静态peer数据
    ngx_uint_t                      current;
    uintptr_t                      *tried; //fzc: 记录每个peer是否尝试过交互的bit数组
    uintptr_t                       data;
} ngx_http_upstream_rr_peer_data_t; //fzc: 动态peer数据, 交互时产生和更新, 见ngx_http_upstream_init_round_robin_peer


ngx_int_t ngx_http_upstream_init_round_robin(ngx_conf_t *cf,
    ngx_http_upstream_srv_conf_t *us);
ngx_int_t ngx_http_upstream_init_round_robin_peer(ngx_http_request_t *r,
    ngx_http_upstream_srv_conf_t *us);
ngx_int_t ngx_http_upstream_create_round_robin_peer(ngx_http_request_t *r,
    ngx_http_upstream_resolved_t *ur);
ngx_int_t ngx_http_upstream_get_round_robin_peer(ngx_peer_connection_t *pc,
    void *data);
void ngx_http_upstream_free_round_robin_peer(ngx_peer_connection_t *pc,
    void *data, ngx_uint_t state);

#if (NGX_HTTP_SSL)
ngx_int_t
    ngx_http_upstream_set_round_robin_peer_session(ngx_peer_connection_t *pc,
    void *data);
void ngx_http_upstream_save_round_robin_peer_session(ngx_peer_connection_t *pc,
    void *data);
#endif


#endif /* _NGX_HTTP_UPSTREAM_ROUND_ROBIN_H_INCLUDED_ */
